﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Documents;
using System.Windows.Markup;
using System.Xml;

using agsXMPP;

using VSTalk.Engine.Core.Context;
using VSTalk.Engine.Core.ExtElement;
using VSTalk.Engine.Core.Feed;
using VSTalk.Model;

namespace VSTalk.Engine.ViewModel.Messenger.ThreadRenderer.BlockBuilder
{
    public class ContentBlockBuilder
    {
        private Client _client;
        
        public ContentBlockBuilder(Client client)
        {
            _client = client;
        }

        public IModelContext ModelContext
        {
            get { return AppServices.Get<IModelContext>(); }
        }

        public Block CreateBlock(IMessage message)
        {
            var header = CreateHeader(message);
            var body = CreateBody(message);
            var block = Join(header, body);
            return block;
        }

        private IEnumerable<Block> CreateBody(IMessage message)
        {
            if (message.XmppMessage.HasTag<XamlBody>())
            {
                var msg = message.XmppMessage.SelectSingleElement<XamlBody>();
                var reader = XmlReader.Create(new StringReader(msg.Content));
                var doc = (FlowDocument)XamlReader.Load(reader);
                return doc.Blocks.ToList();
            }
            var body = message.XmppMessage.Body;
            var span = new Span();
            span.Inlines.Add(body);
            return new[] { new Paragraph(span) };
        }

        private Inline CreateHeader(IMessage message)
        {
            var from = message.XmppMessage.From;
            var date = message.Date;
            var name = GetName(from);
            var span = new Span();
            var format = date >= DateTime.Today
                ? string.Format("{0} {1:t}", name, date)
                : string.Format("{0} {1:g}", name, date);
            span.Inlines.Add(format);
            return new Bold(span);
        }

        private string GetName(Jid @from)
        {
            if (@from == null) return _client.Login;
            var client = ModelContext.GetClientByJid(from);
            if (client != null)
            {
                return client.Login;
            }
            var interlocutor = ModelContext.GetContactByJid(_client.Id, @from);
            if (interlocutor != null)
            {
                return interlocutor.Name;
            }
            var room = ModelContext.GetRoomByJid(_client.Id, @from);
            if (room != null)
            {
                return @from.Resource ?? room.Name;
            }
            return from;
        }

        private Block Join(Inline header, IEnumerable<Block> body)
        {
            var paragraph = new Section();
            paragraph.Blocks.Add(new Paragraph(header));
            foreach (var item in body)
            {
                paragraph.Blocks.Add(item);
            }
            return paragraph;
        }
    }
}